package FileServer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
//import se.lth.cs.fakecamera.Axis211A;
import se.lth.cs.realtime.RTThread;

import Constants.constants;
import Constants.constants.*;

public class Input_Manager extends RTThread {
	private FileServer fileServer;
	private int networkPort;
	private InputStream input;
	private BufferedReader br;

	/**
	 * Skapar en Input_Manager för en Proxy-kamera som har i uppgift att ta emot all 
	 * input och förmedla samt hantera trådarna och information till trådarna.
	 * @param camServer Den CamServer som vi ska använda.
	 * @param camera Den kamera vi ska använda.
	 * @param networkPort Positionen för att koppla mot rätt kamera.
	 * @param ip The IP-adress of the camera we want to connect to.
	 * @param camPort The port on which the communication with the camera will be done
	 */
	public Input_Manager(FileServer camServer, int networkPort) {
		super();
		this.fileServer = camServer;
		this.networkPort = networkPort;
	}

	/**
	 * Trådens run-metod
	 * 1. Vi kopplar upp oss mot kamera och mot klienten.
	 * 2. Vi initierar alla trådar samt startar dem.
	 * 3. Sedan läser vi indata medan vi är uppkopplade och avgör 
	 *    vilken typ av kommando vi har fått samt vilka åtgärder som ska tas.
	 */
	public void run() {
		try {
			
			ServerSocket serverSocket = new ServerSocket(networkPort);
			Socket socket;

			while (true) {
				System.out.println("Waiting for clients to connect..");
				socket = serverSocket.accept();
				boolean connected = true;
				try {
					input = socket.getInputStream();
					br= new BufferedReader(new InputStreamReader(input));
					fileServer.establishOutput(socket.getOutputStream());
					System.out.println("Client connected, input and output established!");
					

					while (connected) {
						byte[] commando = getBytes(4);
						if (constants.compareCommando(commando,constants.TEAR_DOWN_CONNECTION)) {
							connected = false;
						}else if(constants.compareCommando(commando, constants.STRING)){
							System.out.println(readInputString());
						}
					}

				} catch (SocketException s) {
					s.printStackTrace();
				}	
				System.out.println("End of stream");
				socket.close();
				
			}

		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	private String readInputString() {
		try {
			return br.readLine();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Läser nbr antal bytes från InputStream
	 * @param nbr Antal byte som ska läsas.
	 * @return Data som har lästs in.
	 */
	private byte[] getBytes(int nbr) {
		byte[] bytes = new byte[nbr];
		int bytesRead = 0;
		int bytesLeft = bytes.length;
		int status = 0;
		while (true) {
			try {
				status = input.read(bytes, bytesRead, bytesLeft);
			} catch (IOException e) {
				break;
			}
			bytesRead += status;
			bytesLeft -= status;
			if (bytesLeft == 0) {
				break;
			}
		}
		return bytes;
	}

}
